<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>VerifyCode</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        html,body{
            height: 100%;
            display: flex;
            gap: 20px;
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }
        .verify-code{
            display: flex;
            align-items: center;
        }
        .message.success{
            color: green;
        }
        .message.err{
            color: red;
        }
        input{
            margin-right: 10px;
            height: 40px;
        }
    </style>
</head>
<body>
    <div class="message">请输入</div>
    <div class="verify-code">
        <input type="text" id="input" placeholder="请输入验证码">
        <canvas id="canvas" width="120" height="40"></canvas>
    </div>
</body>
<script>
    //  随机数
    function randomNum(min, max) {
        return Math.floor(Math.random() * (max - min) + min);
    }
    //  随机颜色
    function randomColor(min, max) {
        return 'rgb(' + randomNum(min, max) + ',' + randomNum(min, max) + ',' + randomNum(min, max) + ')';
    }

    let width = 120
    let height = 40
    let canvas = document.getElementById('canvas')
    const input = document.getElementById('input')
    const message = document.querySelector('.message')
    let ctx = canvas.getContext('2d')
    

    const options = {
        length: 5,
    }
    // 随机字符串
    const pool = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
    let str = ''

    function update(){
        ctx.clearRect(0, 0, width, height)
        ctx.fillStyle = randomColor(180, 240)    
        ctx.fillRect(0, 0, width, height)
            str = ''
            for (let i = 0; i < options.length; i++) {
                let letter = pool[randomNum(0, pool.length)]
                str += letter
                // 随机大小
                let fs = randomNum(18, 30)
                // 随机旋转角度
                let deg = randomNum(-20,20)

                ctx.font = `${fs}px Arial`
                ctx.textBaseline = 'top' // 对齐方式 与指定 y 坐标对齐 文字顶部与传入 y 坐标对齐
                // 随机颜色
                ctx.fillStyle = randomColor(50, 160)
                ctx.save()
                ctx.translate(width / options.length * i,0) // 平移原点
                ctx.rotate(deg * Math.PI / 180) // 旋转坐标系
                ctx.fillText(letter,0, height/3)
                ctx.restore()
            }
            // 随机生成干扰线
            for (let i = 0; i < options.length + 2; i++) {
                ctx.beginPath()
                ctx.moveTo(randomNum(0, width), randomNum(0, height))
                ctx.lineTo(randomNum(0, width), randomNum(0, height))
                ctx.strokeStyle = randomColor(50, 160)
                ctx.closePath()
                ctx.stroke()
            }
            // console.log(str);
    }
    function validateInput(){
        if(input.value.toUpperCase() === str.toUpperCase()){
            message.innerHTML = '验证码正确'
            message.classList.add('success')
            message.classList.remove('err')
            update()
        }else{
            message.innerHTML = '验证码错误'
            message.classList.add('err')
            message.classList.remove('success')
        }
    }
    // 事件监听
    canvas.onclick = function(){
        update()
    }
    input.onblur = function(){
        validateInput()
    }
    input.addEventListener('keydown',function(e){
        if(e.key === 'Enter'){
            validateInput()
        }
    })
    update()
</script>
</html>